﻿using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace DBMC_Core
{
    public class Minecraft
    {
        public bool StartGame(string JavaPath, string command, string successIndicator)
        {
            try
            {
                // 设置进程启动信息
                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = JavaPath,
                    Arguments = command,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                };

                // 启动进程，并获取输出
                using (Process process = new Process { StartInfo = psi })
                {
                    bool isSuccess = false;
                    StringBuilder output = new StringBuilder();
                    StringBuilder error = new StringBuilder();

                    process.OutputDataReceived += (sender, e) =>
                    {
                        if (!string.IsNullOrEmpty(e.Data))
                        {
                            output.AppendLine(e.Data);
                            // 检查输出是否包含成功指示字符串
                            if (e.Data.Contains(successIndicator))
                            {
                                isSuccess = true;
                                // 可选：找到成功消息后停止进程
                                // process.Kill();
                            }
                        }
                    };
                    process.ErrorDataReceived += (sender, e) =>
                    {
                        if (!string.IsNullOrEmpty(e.Data))
                        {
                            error.AppendLine(e.Data);
                        }
                    };

                    process.Start();
                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    // 等待进程退出或成功指示出现
                    // 注意：这里可能需要设定一个合理的超时时间以避免无限等待
                    while (!process.HasExited && !isSuccess)
                    {
                        // 设定检查间隔，这里是100毫秒
                        process.WaitForExit(100);
                    }

                    // 捕获日志可能对调试有帮助
                    string fullOutput = output.ToString();
                    string fullError = error.ToString();

                    return isSuccess && process.ExitCode == 0;
                }
            }
            catch (Exception)
            {
                // 可以根据需要记录异常信息
                // 例如: LogError(ex.ToString());
                return false;
            }
        }

        public async Task<string> StartGameToLog(string JavaPath, string command)
        {
            try
            {
                // 设置进程启动信息
                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = JavaPath,
                    Arguments = command,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                };

                // 启动进程，并获取输出
                using (Process process = new Process { StartInfo = psi })
                {
                    StringBuilder output = new StringBuilder();
                    StringBuilder error = new StringBuilder();

                    process.OutputDataReceived += (sender, e) => { output.AppendLine(e.Data); };
                    process.ErrorDataReceived += (sender, e) => { error.AppendLine(e.Data); };

                    process.Start();

                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    await Task.Run(() => process.WaitForExit());
                    return error.Length > 0 ? error.ToString() : output.ToString();
                }
            }
            catch
            {
                return null;
            }
        }

        public int TokenExpires => 86400;
        public string JavaPath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data", "java");
        public string JavaCorePath => Path.Combine(JavaPath, "bin", "java.exe");
        public string GamePath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data", ".minecraft");
        public string AssetsPath => Path.Combine(GamePath, "assets");
        public string VersionsPath => Path.Combine(GamePath, "versions");
        public string LibrariesPath => Path.Combine(GamePath, "libraries");
        public string SavesPath => Path.Combine(GamePath, "saves");
        public string ScreenshotsPath => Path.Combine(GamePath, "screenshots");
        public string ModsPath => Path.Combine(GamePath, "mods");


        public bool CheckJavaVersion
        {
            get
            {
                try
                {
                    // 设置进程启动信息
                    ProcessStartInfo psi = new ProcessStartInfo
                    {
                        FileName = "java", // 命令名称
                        Arguments = "-version", // 带上-version参数
                        RedirectStandardError = true, // 重定向错误流
                        UseShellExecute = false, // 不使用系统外壳程序启动
                        CreateNoWindow = true // 不创建窗口
                    };

                    // 启动进程，并获取输出
                    using (Process process = Process.Start(psi))
                    {
                        if (process != null)
                        {
                            // 读取错误流得到Java版本信息
                            string errorOutput = process.StandardError.ReadToEnd();

                            // 等待进程结束
                            process.WaitForExit();

                            // 使用正则表达式匹配"1.8.0"
                            return Regex.IsMatch(errorOutput, @"1\.8\.0");
                        }
                        else
                        {
                            // 如果进程没有启动，则认为没有找到匹配的版本
                            return false;
                        }
                    }
                }
                catch
                {
                    // 如果发生异常，也认为没有找到匹配的版本
                    return false;
                }
            }
        }

        public string ConvertToUUID(string guidString)
        {
            if (guidString.Length == 32)
            {
                // 插入连字符，让字符串符合标准GUID格式8-4-4-4-12
                string formattedGuidString = guidString.Insert(20, "-")
                                                      .Insert(16, "-")
                                                      .Insert(12, "-")
                                                      .Insert(8, "-");

                if (Guid.TryParse(formattedGuidString, out Guid newGuid))
                {
                    return newGuid.ToString();
                }
            }

            return null;
        }

        public bool CheckUseJavaVersion(string javapath)
        {
            try
            {
                // 设置进程启动信息
                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = javapath, // 命令名称
                    Arguments = "-version", // 带上-version参数
                    RedirectStandardError = true, // 重定向错误流
                    UseShellExecute = false, // 不使用系统外壳程序启动
                    CreateNoWindow = true // 不创建窗口
                };

                // 启动进程，并获取输出
                using (Process process = Process.Start(psi))
                {
                    if (process != null)
                    {
                        // 读取错误流得到Java版本信息
                        string errorOutput = process.StandardError.ReadToEnd();

                        // 等待进程结束
                        process.WaitForExit();

                        // 使用正则表达式匹配"1.8.0"
                        return Regex.IsMatch(errorOutput, @"1\.8\.0");
                    }
                    else
                    {
                        // 如果进程没有启动，则认为没有找到匹配的版本
                        return false;
                    }
                }
            }
            catch
            {
                // 如果发生异常，也认为没有找到匹配的版本
                return false;
            }
        }

        public bool IsJava
        {
            get
            {
                if (!Directory.Exists(JavaPath))
                {
                    if (!Directory.Exists(JavaCorePath))
                    {
                        return false;
                    }
                }
                return true;
            }
        }

        public string ConvertToPath(string input)
        {
            var parts = input.Split(':');
            if (parts.Length != 3)
            {
                throw new ArgumentException("Input must be in the format 'packageName:name:version'");
            }

            var packageName = parts[0].Replace(".", "/");
            var name = parts[1];
            var version = parts[2];

            return $"{packageName}/{name}/{version}/{name}-{version}.jar";
        }

        public string GetLibraries
        {
            get
            {
                string filePath = new Danbai().VersionsJson;
                string jsonContent = File.ReadAllText(filePath);
                JObject jsonObj = JObject.Parse(jsonContent);
                JArray libraries = (JArray)jsonObj["libraries"];
                StringBuilder sb = new StringBuilder();

                foreach (JObject library in libraries)
                {
                    string name = library["name"].ToString();
                    string[] parts = name.Split(':');
                    if (parts.Length == 3)
                    {
                        string package = parts[0].Replace(".", @"\");
                        string artifact = parts[1];
                        string version = parts[2];

                        string path = $@"{package}\{artifact}\{version}\{artifact}-{version}.jar";
                        string fullPath = Path.Combine(LibrariesPath, path);
                        sb.Append(fullPath + ";");
                    }
                }

                return sb.ToString();
            }
        }

        public List<string> InitCommand = new List<string>
        {
            "-Dfile.encoding=GB18030",
            "-Dsun.stdout.encoding=GB18030",
            "-Dsun.stderr.encoding=GB18030",
            "-Djava.rmi.server.useCodebaseOnly=true",
            "-Dcom.sun.jndi.rmi.object.trustURLCodebase=false",
            "-Dcom.sun.jndi.cosnaming.object.trustURLCodebase=false",
            "-Dlog4j2.formatMsgNoLookups=true",
            "-XX:+UnlockExperimentalVMOptions",
            "-XX:+UseG1GC",
            "-XX:G1NewSizePercent=20",
            "-XX:G1ReservePercent=20",
            "-XX:MaxGCPauseMillis=50",
            "-XX:G1HeapRegionSize=32m",
            "-XX:-UseAdaptiveSizePolicy",
            "-XX:-OmitStackTraceInFastThrow",
            "-XX:-DontCompileHugeMethods",
            "-Dfml.ignoreInvalidMinecraftCertificates=true",
            "-Dfml.ignorePatchDiscrepancies=true",
            "-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump",
            "-Dminecraft.launcher.brand=DBMC",
            "-Dminecraft.launcher.version=1.0.0.5",
        };

        public void SetMaxMemory(int num)
        {
            InitCommand.Add($"-Xmx{num}m");
        }

        public void SetDanbaiUserInfo(string name, string uuid, string accessToken)
        {
            InitCommand.Add($"--username {name}");
            InitCommand.Add($"--version \"{new Danbai().VersionsName}\"");
            InitCommand.Add($"--versionType DBMC");
            InitCommand.Add($"--gameDir \"{GamePath}\"");
            InitCommand.Add($"--assetsDir \"{AssetsPath}\"");
            InitCommand.Add($"--assetIndex 1.7.10");
            InitCommand.Add($"--uuid {uuid}");
            InitCommand.Add($"--accessToken {accessToken}");
            InitCommand.Add("--userProperties {}");
            InitCommand.Add($"--userType msa");
            InitCommand.Add($"--width 854");
            InitCommand.Add($"--height 480");
        }

        public string Command => string.Join(" ", InitCommand);

        public bool IsDanBaiGameReady
        {
            get
            {
                if (Directory.Exists(GamePath))
                {
                    if (Directory.Exists(new Danbai().Versions))
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
        }

        public string GetHeadImage(string name)
        {
            return "https://mineskin.eu/helm/" + $"{name}" + "/100.png";
        }

        /// <summary>
        /// 获取Minecraft档案
        /// </summary>
        /// <param name="token">MinecraftToken</param>
        /// <returns>返回Json数据</returns>
        public async Task<string> GetMinecraftProfile(string token)
        {
            RestClient client = new RestClient("https://api.minecraftservices.com/minecraft/profile");
            RestRequest request = new RestRequest
            {
                Method = Method.Get,
                Timeout = 30000,
            };
            request.AddHeader("Authorization", $@"Bearer {token}");
            request.AddHeader("Host", "api.minecraftservices.com");
            RestResponse response = await client.ExecuteAsync(request);
            return response.Content;
        }
    }

    public class MinecraftCommand
    {
        public class TargetSelector
        {
            private string selectorString;

            private TargetSelector(string selector)
            {
                selectorString = selector;
            }

            public override string ToString()
            {
                return selectorString;
            }

            public static TargetSelector NearbyPlayers => new TargetSelector("@p");
            public static TargetSelector AllPlayers => new TargetSelector("@a");
            public static TargetSelector RandomPlayer => new TargetSelector("@r");
            public static TargetSelector PlayerName(string name) => new TargetSelector(name);
        }

        public enum Gamemode
        {
            Creative,
            Survival,
            Adventure
        }

        public enum Gamerules
        {
            commandBlockOutput,
            disableElytraMovementCheck,
            doDaylightCycle,
            doFireTick,
            doMobLoot,
            doMobSpawning,
            doTileDrops,
            keepInventory,
            mobGriefing,
            naturalRegeneration,
            openblocks_Spawn_graves
        }

        public enum Time
        {
            Set,
            Add
        }

        public class TimeSubParameter
        {
            private int timeModeValue;
            public enum Time
            {
                Morning = 1000,
                Noon = 6000,
                Night = 11000,
                Midnight = 18000
            }
            public object TimeMode
            {
                get
                {
                    if (Enum.IsDefined(typeof(Time), timeModeValue))
                    {
                        return (Time)timeModeValue;
                    }
                    return timeModeValue;
                }
                set
                {
                    if (value is Time)
                    {
                        timeModeValue = (int)value;
                    }
                    else if (value is int)
                    {
                        timeModeValue = (int)value;
                    }
                    else
                    {
                        throw new ArgumentException("TimeMode must be a value of the Time enum or an int.");
                    }
                }
            }
        }

        public class TextJson
        {
            public string Text;
            public McTextColor Color;
            public bool Bold;
            public bool italic;
            public bool underlined;
            public bool strikethrough;
            public bool obfuscated;
            public string insertion;
            public MCclickEvent clickEvent;
            public MChoverEvent hoverEvent;
        }

        public enum McTextColor
        {
            black,
            dark_blue,
            dark_green,
            dark_aqua,
            dark_red,
            dark_purple,
            gold,
            gray,
            dark_gray,
            blue,
            green,
            aqua,
            red,
            light_purple,
            yellow,
            white
        }

        public class MCclickEvent
        {
            public MCclickEventAction action;
            public string value;
            public enum MCclickEventAction
            {
                run_command,
                open_url,
                suggest_command
            }
        }

        public class MChoverEvent
        {
            public MChoverEventAction action;
            public MChoverEventValue value;

            public enum MChoverEventAction
            {
                show_text,
                show_item,
                show_entity,
                show_achievement
            }
            public class MChoverEventValue
            {
                public Show_item show_item;
                public Show_Entity show_entity;
                public string show_achievement;

                public class Show_item
                {
                    public string id { get; set; }

                    public TagInfo tag { get; set; }

                    public class TagInfo
                    {
                        public DisplayInfo Display { get; set; }

                        public class DisplayInfo
                        {
                            public string Name { get; set; }

                            public List<TextJson> Lore { get; set; }

                            public DisplayInfo(string name, List<TextJson> lore)
                            {
                                Name = name;
                                Lore = lore;
                            }
                        }
                    }

                }
                public class Show_Entity
                {
                    public int type;
                    public string name;
                    public int id;
                }

                public string Show_achievement(string name)
                {
                    return $"achievement.{name}";
                }

                public string Show(string name)
                {
                    return $"stat.{name}";
                }
            }
        }

        public class Generate
        {
            public static string GenerateTextJson(List<TextJson> textJsonList)
            {
                JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings
                {
                    Converters = new List<JsonConverter>
                {
                    new StringEnumConverter(new CamelCaseNamingStrategy())
                },
                    ContractResolver = new CamelCasePropertyNamesContractResolver(),
                    Formatting = Formatting.None,
                    DefaultValueHandling = DefaultValueHandling.Ignore
                };

                string jsonString = JsonConvert.SerializeObject(textJsonList, jsonSerializerSettings);

                return jsonString;
            }

            public static string SetGamemode(Gamemode gamemode)
            {
                return $"/gamemode {gamemode.ToString().ToLower()}";
            }

            public static string SetGamerule(Gamerules gamerules, bool subParameter)
            {
                return $"/gamerule {gamerules.ToString().ToLower()} {subParameter.ToString().ToLower()}";
            }

            public static string SetTime(Time time, TimeSubParameter timeSubParameter)
            {
                return $"/time {time.ToString().ToLower()} {timeSubParameter}";
            }

            public static string SetTellraw(TargetSelector targetSelector , List<TextJson> textJsonList)
            {
                JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings
                {
                    Converters = new List<JsonConverter>
                {
                    new StringEnumConverter(new CamelCaseNamingStrategy())
                },
                    ContractResolver = new CamelCasePropertyNamesContractResolver(),
                    Formatting = Formatting.None,
                    DefaultValueHandling = DefaultValueHandling.Ignore
                };

                string jsonString = JsonConvert.SerializeObject(textJsonList, jsonSerializerSettings);

                return $"/tellraw {targetSelector} {jsonString}";
            }

            public static void Test()
            {
                List<TextJson> textJsonList = new List<TextJson>
                {
                    new TextJson
                    {
                        Text = "First Message",
                        Color = McTextColor.gold,
                        Bold = true
                    },
                    new TextJson
                    {
                        Text = "Second Message",
                        Color = McTextColor.dark_aqua
                    }
                };
                Console.WriteLine(SetTellraw(TargetSelector.NearbyPlayers, textJsonList));
            }
        }
    }

    public class Danbai
    {
        public static string HandImage => "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";
        public string VersionsName => "Grand Theft Auto V-MC";
        public string Versions => Path.Combine(new Minecraft().VersionsPath, VersionsName);
        public string Natives => Path.Combine(Versions, "natives");
        public string Log4j2 => Path.Combine(Versions, "log4j2.xml");
        public string Core => Path.Combine(Versions, $"{VersionsName}.jar");
        public string VersionsJson => Path.Combine(Versions, $"{VersionsName}.json");
    }

    public class TokenGenerator
    {
        public string SetToken
        {
            get
            {
                string token = GenerateRandomToken(16);
                Console.WriteLine($"AccessToken: {token}");
                return token;
            }
        }

        private static string GenerateRandomToken(int byteLength)
        {
            using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
            {
                byte[] randomBytes = new byte[byteLength];
                rng.GetBytes(randomBytes);
                // 将字节转换为十六进制字符串
                return BitConverter.ToString(randomBytes).Replace("-", "").ToLowerInvariant();
            }
        }
    }
}
